package com.mlming.simpledb.backend.dm.logger;

import com.mlming.simpledb.backend.utils.Panic;
import com.mlming.simpledb.backend.utils.Parser;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import com.mlming.simpledb.common.Error;

public interface Logger {
    void log(byte[] data); // 添加一条日志记录
    void truncate(long x) throws Exception; // 把log文件从x位置截断
    byte[] next(); // 读取一条日志记录, 同时指针移动到下一条日志开始位置(类似于迭代器)
    void rewind(); // "倒回" 将指针移动回到日志文件的第一条日志记录的开始位置(即: 4字节(XCheckSum)之后)
    void close(); // 关闭日志文件

    // 在指定路径创建一个.log文件, 并创建一个LoggerImpl实例
    public static Logger create(String path) {
        File f = new File(path+LoggerImpl.LOG_SUFFIX);
        try {
            if(!f.createNewFile()) {
                Panic.panic(Error.FileExistsException);
            }
        } catch (Exception e) {
            Panic.panic(e);
        }
        if(!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(f, "rw");
            fc = raf.getChannel();
        } catch (FileNotFoundException e) {
            Panic.panic(e);
        }

        ByteBuffer buf = ByteBuffer.wrap(Parser.int2Byte(0));
        try {
            fc.position(0);
            fc.write(buf);
            fc.force(false);
        } catch (IOException e) {
            Panic.panic(e);
        }

        return new LoggerImpl(raf, fc, 0);
    }
    // 通过指定路径的.log文件, 创建一个LoggerImpl实例
    public static Logger open(String path) {
        File f = new File(path+LoggerImpl.LOG_SUFFIX);
        if(!f.exists()) {
            Panic.panic(Error.FileNotExistsException);
        }
        if(!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(f, "rw");
            fc = raf.getChannel();
        } catch (FileNotFoundException e) {
            Panic.panic(e);
        }
        LoggerImpl lg = new LoggerImpl(raf, fc);
        // 要执行init方法, 通过log文件来初始化参数
        lg.init();
        return lg;
    }
}
